package at.fhj.itm.weather;

import java.io.InputStream;
import java.net.URL;
import java.util.Observable;
import java.util.Observer;

import android.app.Activity;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.TextView;

/**
 * 
 * @author Christian Tassler & Andreas Reibenbacher
 * 
 */
public class WetterApp extends Activity implements Observer, OnClickListener,
		LocationListener, OnCheckedChangeListener {

	private Settings settings;
	private WeatherDataLoader weatherLoader;
	private LocationManager locationManager;

	//Menu Fields
	private EditText locationInput;
	//Result Fields
	private TextView luftdruck;
	private TextView luftfeuchte;
	private TextView wind;
	private TextView sunrise;
	private TextView sunset;
	private TextView info;
	private TextView location;
	private TextView temperature;
	private TextView infoText;
	private TextView dateTomorrow;
	private TextView tomorrowLowTemp;
	private TextView tomorrowHigTemp;
	private TextView infoTextTomorrow;
	private TextView date2Days;
	private TextView twoDaysLowTemp;
	private TextView twoDaysHigTemp;
	private TextView infoText2Days;
	private TextView forecast;

	private ImageView todayImage;
	private ImageView TomorrowImage;
	private ImageView twoDaysImage;

	// to prevent multiple web queries at settings change
	private boolean ignoreFirstGPSSignal = false;

	
	
	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		this.settings = new Settings(this);

		// setup the layout
		locationInput = ((EditText) findViewById(R.id.locationInput));
		locationInput.setText(settings.getHome() != null ? settings.getHome()
				: "City");
		// setup the buttons
		((Button) findViewById(R.id.okButton)).setOnClickListener(this);
		((Button) findViewById(R.id.loadHome)).setOnClickListener(this);
		((Button) findViewById(R.id.saveHome)).setOnClickListener(this);
		((Button) findViewById(R.id.backButton)).setOnClickListener(this);

		CheckBox gpsLoadAtStart = ((CheckBox) findViewById(R.id.gpsLoadAtStart));
		gpsLoadAtStart.setOnCheckedChangeListener(this);
		gpsLoadAtStart.setChecked(settings.isGpsLoadAtStart());

		CheckBox gpsReloading = ((CheckBox) findViewById(R.id.gpsReloading));
		gpsReloading.setOnCheckedChangeListener(this);
		gpsReloading.setChecked(settings.isGpsReloading());

		CheckBox startWithResult = ((CheckBox) findViewById(R.id.startWithResult));
		startWithResult.setOnCheckedChangeListener(this);
		startWithResult.setChecked(settings.isStartWithResult());

		RadioButton oneKm = ((RadioButton) findViewById(R.id.radioOneKm));
		RadioButton tenKm = ((RadioButton) findViewById(R.id.radioTenKm));
		RadioButton twentyFiveKm = ((RadioButton) findViewById(R.id.radioTwentyFive));
		switch (settings.getGPSMinDistance()) {
		case 1000:
			oneKm.setChecked(true);
			break;
		case 10000:
			tenKm.setChecked(true);
			break;
		case 25000:
			twentyFiveKm.setChecked(true);
			break;
		}
		oneKm.setOnCheckedChangeListener(this);
		tenKm.setOnCheckedChangeListener(this);
		twentyFiveKm.setOnCheckedChangeListener(this);

		// Initialization of the view elements at the result

		luftdruck = (TextView) findViewById(R.id.luftdruck);
		luftfeuchte = (TextView) findViewById(R.id.luftfeuchte);
		wind = (TextView) findViewById(R.id.wind);
		sunrise = (TextView) findViewById(R.id.sunrise);
		sunset = (TextView) findViewById(R.id.sunset);
		info = (TextView) findViewById(R.id.info);
		location = (TextView) findViewById(R.id.location);
		temperature = (TextView) findViewById(R.id.temp);
		infoText = (TextView) findViewById(R.id.infoText);
		dateTomorrow = (TextView) findViewById(R.id.dateTomorrow);
		tomorrowLowTemp = (TextView) findViewById(R.id.tempLowTommorow);
		tomorrowHigTemp = (TextView) findViewById(R.id.tempHighTommorow);
		infoTextTomorrow = (TextView) findViewById(R.id.infoTomorrow);
		date2Days = (TextView) findViewById(R.id.date2Days);
		twoDaysLowTemp = (TextView) findViewById(R.id.tempLow2Days);
		twoDaysHigTemp = (TextView) findViewById(R.id.tempHigh2Days);
		infoText2Days = (TextView) findViewById(R.id.info2Days);
		forecast = (TextView) findViewById(R.id.forecast);

		todayImage = (ImageView) findViewById(R.id.imageToday);
		TomorrowImage = (ImageView) findViewById(R.id.widget45);
		twoDaysImage = (ImageView) findViewById(R.id.widget52);

	}

	

	@Override
	protected void onStart() {
		showMenu();
		Log.i("WeatherApp", settings.toString());
		if (settings.isGpsLoadAtStart())
			initGps(settings.isStartWithResult());
		else if (settings.isStartWithResult()
				&& settings.getHome().length() > 0)
			loadWeather(settings.getHome());

		super.onStart();
	}

	@Override
	protected void onPause() {
		settings.saveValues();
		stopGps();
		super.onPause();
	}

	
	/**
	 * Responsible for loading the image from an URL
	 * @param url from the image
	 * @return a drawable object
	 */
	private Drawable loadImageFromWebOperations(String url) {
		try {
			InputStream is = (InputStream) new URL(url).getContent();
			Drawable d = Drawable.createFromStream(is, "src name");
			return d;
		} catch (Exception e) {
			Log.e("WeatherApp", "Could not load Image from url " + url);
			return null;
		}
	}
	
	public void loadWeather(String address) {
		weatherLoader = WeatherDataLoader.createYahooLoader();
		weatherLoader.addObserver(this);

		weatherLoader.loadData(address);
	}

	
	/*
	 * Listeners
	 */
	
	//for buttons
	public void onClick(View v) {
		if (v == findViewById(R.id.okButton)) {
			loadWeather(locationInput.getText().toString());
		} else if (v == findViewById(R.id.loadHome)) {
			locationInput.setText(settings.getHome());
		} else if (v == findViewById(R.id.saveHome)) {
			settings.setHome(locationInput.getText().toString());
		} else if (v == findViewById(R.id.backButton)) {
			showMenu();
		}
	}

	//for radios, checkboxes
	public void onCheckedChanged(CompoundButton button, boolean isChecked) {
		if (button == findViewById(R.id.gpsLoadAtStart)) {
			settings.setGpsLoadAtStart(isChecked);
			findViewById(R.id.gpsReloading).setVisibility(
					isChecked ? View.VISIBLE : View.INVISIBLE);
			findViewById(R.id.radioGroup).setVisibility(
					isChecked ? View.VISIBLE : View.INVISIBLE);
			if (isChecked)
				initGps(true);
			else
				stopGps();
		} else if (button == findViewById(R.id.gpsReloading)) {
			settings.setGpsReloading(isChecked);
			findViewById(R.id.radioGroup).setVisibility(
					isChecked ? View.VISIBLE : View.INVISIBLE);
			if (isChecked)
				initGps(false);
			else
				stopGps();
		} else if (button == findViewById(R.id.startWithResult)) {
			settings.setStartWithResult(isChecked);
			if (isChecked)
				initGps(false);
			else
				stopGps();
		}

		else if (button == findViewById(R.id.radioOneKm)) {
			settings.setGPSMinDistance(1000);
		} else if (button == findViewById(R.id.radioTenKm)) {
			settings.setGPSMinDistance(10000);
		} else if (button == findViewById(R.id.radioTwentyFive)) {
			settings.setGPSMinDistance(25000);
		}
	}

	//called when weather finished loading
	public void update(Observable observable, Object data) {
		if (data == null) {
			showMenu();
			locationInput.setText("not found");
			return;
		}

		if (data instanceof WeatherData) {
			WeatherData resultWeather = (WeatherData) data;

			// Information of the several result Views will be published
			luftdruck.setText("Pressure: " + resultWeather.getPressure() + " "
					+ resultWeather.getPressureUnit());
			luftfeuchte.setText("Humidity: " + resultWeather.getHumidity()
					+ " %");
			wind.setText("Wind: " + resultWeather.getSpeedWind() + " "
					+ resultWeather.getSpeedUnit() + " "
					+ resultWeather.getDirectionWind());
			sunrise.setText("Sunrise: " + resultWeather.getSunrise());
			sunset.setText("Sunset: " + resultWeather.getSunset());
			info.setText(resultWeather.getInfo());
			location.setText(resultWeather.getCity() + ", "
					+ resultWeather.getCountry());
			temperature.setText(resultWeather.getTemperature() + " "
					+ resultWeather.getUnitTemperature());
			infoText.setText(resultWeather.getInfoText());
			dateTomorrow.setText(resultWeather.getDayTomorrow() + " "
					+ resultWeather.getDateTomorrow());
			tomorrowLowTemp.setText(resultWeather.getTempLowTomorrow() + " "
					+ resultWeather.getUnitTemperature());
			tomorrowHigTemp.setText(resultWeather.getTempHighTomorrow() + " "
					+ resultWeather.getUnitTemperature());
			infoTextTomorrow.setText(resultWeather.getInfoTomorrow());
			date2Days.setText(resultWeather.getDay2Days() + " "
					+ resultWeather.getDate2Days());
			twoDaysLowTemp.setText(resultWeather.getTempLow2Days() + " "
					+ resultWeather.getUnitTemperature());
			twoDaysHigTemp.setText(resultWeather.getTempHigh2Days() + " "
					+ resultWeather.getUnitTemperature());
			infoText2Days.setText(resultWeather.getInfo2Days());

			Drawable drawable = loadImageFromWebOperations("http://l.yimg.com/a/i/us/we/52/"
					+ resultWeather.getCode() + ".gif");
			todayImage.setImageDrawable(drawable);
			Drawable drawableTomorrow = loadImageFromWebOperations("http://l.yimg.com/a/i/us/we/52/"
					+ resultWeather.getCodeTomorrow() + ".gif");
			TomorrowImage.setImageDrawable(drawableTomorrow);
			Drawable drawable2Days = loadImageFromWebOperations("http://l.yimg.com/a/i/us/we/52/"
					+ resultWeather.getCode2Days() + ".gif");
			twoDaysImage.setImageDrawable(drawable2Days);

			showResult();
		}
	}

	/*
	 * Menu - Result switch
	 */
	
	private void showResult() {
		findViewById(R.id.mainView).setVisibility(View.INVISIBLE);
		setAllResultElements(View.VISIBLE);
		InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
		imm.hideSoftInputFromWindow(locationInput.getWindowToken(), 0);
	}

	private void showMenu() {
		findViewById(R.id.mainView).setVisibility(View.VISIBLE);
		setAllResultElements(View.INVISIBLE);
	}
	
	/**
	 * Method is responsible for setting the visibility of all result elements
	 */
	public void setAllResultElements(int visibility) {
		luftdruck.setVisibility(visibility);
		luftfeuchte.setVisibility(visibility);
		wind.setVisibility(visibility);
		sunrise.setVisibility(visibility);
		sunset.setVisibility(visibility);
		info.setVisibility(visibility);
		location.setVisibility(visibility);
		temperature.setVisibility(visibility);
		infoText.setVisibility(visibility);
		dateTomorrow.setVisibility(visibility);
		tomorrowLowTemp.setVisibility(visibility);
		tomorrowHigTemp.setVisibility(visibility);
		infoTextTomorrow.setVisibility(visibility);
		date2Days.setVisibility(visibility);
		twoDaysLowTemp.setVisibility(visibility);
		twoDaysHigTemp.setVisibility(visibility);
		infoText2Days.setVisibility(visibility);
		forecast.setVisibility(visibility);

		todayImage.setVisibility(visibility);
		TomorrowImage.setVisibility(visibility);
		twoDaysImage.setVisibility(visibility);

		((Button) findViewById(R.id.backButton)).setVisibility(visibility);
	}

	/*
	 * GPS
	 */
	
	private void initGps(boolean showFirstResult) {
		stopGps();
		if (locationManager == null) {
			locationManager = (LocationManager) this
					.getSystemService(Context.LOCATION_SERVICE);
		}
		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 60000,
				settings.getGPSMinDistance(), this);
		if (!showFirstResult)
			ignoreFirstGPSSignal = true;
	}

	private void stopGps() {
		if (locationManager != null)
			locationManager.removeUpdates(this);
	}
	
	public void onLocationChanged(Location location) {
		if (ignoreFirstGPSSignal) {
			ignoreFirstGPSSignal = false;
			return;
		}

		Log.i("WeatherApp", "new location: " + location);

		double lat = location.getLatitude();
		double lng = location.getLongitude();

		String city = WeatherDataYahoo.getPlaceFromGeo(lat, lng);
		((EditText) findViewById(R.id.locationInput)).setText(city);
		if (!settings.isStartWithResult())
			return;
		if (!settings.isGpsReloading())
			stopGps();
		loadWeather(city);
	}

	public void onProviderDisabled(String arg0) {
	}

	public void onProviderEnabled(String arg0) {
	}

	public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
	}

}